/**
 * 增强的API中间件
 * 集成验证、错误处理、限流和监控功能
 */

const ValidationService = require('../services/validationService.cjs');

class EnhancedMiddleware {
  constructor(options = {}) {
    this.validationService = new ValidationService();
    this.options = {
      enableValidation: options.enableValidation !== false,
      enableRateLimit: options.enableRateLimit !== false,
      enableMetrics: options.enableMetrics !== false,
      rateLimitWindow: options.rateLimitWindow || 60000, // 1分钟
      rateLimitMax: options.rateLimitMax || 200, // 增加到每分钟200次请求
      ...options
    };
    
    this.requestCounts = new Map();
    this.metrics = {
      totalRequests: 0,
      successfulRequests: 0,
      failedRequests: 0,
      validationErrors: 0,
      rateLimitExceeded: 0
    };
  }

  /**
   * 限流中间件
   */
  rateLimit() {
    return (req, res, next) => {
      if (!this.options.enableRateLimit) {
        return next();
      }

      const clientId = this.getClientId(req);
      const now = Date.now();
      const windowStart = now - this.options.rateLimitWindow;

      // 清理过期的请求记录
      this.cleanupExpiredRequests(windowStart);

      // 获取客户端请求记录
      if (!this.requestCounts.has(clientId)) {
        this.requestCounts.set(clientId, []);
      }

      const clientRequests = this.requestCounts.get(clientId);
      
      // 移除窗口外的请求
      const validRequests = clientRequests.filter(timestamp => timestamp > windowStart);
      this.requestCounts.set(clientId, validRequests);

      // 检查是否超过限制
      if (validRequests.length >= this.options.rateLimitMax) {
        this.updateMetrics('rateLimitExceeded');
        return res.status(429).json({
          success: false,
          error: '请求频率过高，请稍后再试',
          retryAfter: Math.ceil(this.options.rateLimitWindow / 1000)
        });
      }

      // 记录当前请求
      validRequests.push(now);
      next();
    };
  }

  /**
   * 错误处理中间件
   */
  errorHandler() {
    return (error, req, res, next) => {
      console.error('API错误:', error);
      this.updateMetrics('failed');

      // 数据库错误
      if (error.code && error.code.startsWith('SQLITE_')) {
        return res.status(500).json({
          success: false,
          error: '数据库操作失败',
          code: 'DATABASE_ERROR'
        });
      }

      // 验证错误
      if (error.name === 'ValidationError') {
        return res.status(400).json({
          success: false,
          error: '数据验证失败',
          details: error.details
        });
      }

      // 默认错误处理
      res.status(500).json({
        success: false,
        error: '服务器内部错误',
        code: 'INTERNAL_ERROR'
      });
    };
  }

  /**
   * 请求监控中间件
   */
  requestMonitor() {
    return (req, res, next) => {
      if (!this.options.enableMetrics) {
        return next();
      }

      const startTime = Date.now();
      this.updateMetrics('total');

      // 监听响应完成
      res.on('finish', () => {
        const duration = Date.now() - startTime;
        
        if (res.statusCode >= 200 && res.statusCode < 400) {
          this.updateMetrics('successful');
        } else {
          this.updateMetrics('failed');
        }

        // 记录慢请求
        if (duration > 5000) {
          console.warn(`慢请求检测: ${req.method} ${req.path} - ${duration}ms`);
        }
      });

      next();
    };
  }

  /**
   * 响应格式化中间件
   */
  responseFormatter() {
    return (req, res, next) => {
      // 保存原始的json方法
      const originalJson = res.json;

      // 重写json方法
      res.json = function(data) {
        try {
          // 若已设置错误状态码，统一输出 success:false，且不再包裹
          if (this.statusCode && this.statusCode >= 400) {
            const body = (data && typeof data === 'object') ? { success: false, ...data } : { success: false, data };
            return originalJson.call(this, body);
          }

          // 若返回体已包含 success 或 error 字段，则视为业务层自定义结构，直接透传
          if (data && typeof data === 'object' && (('success' in data) || ('error' in data))) {
            // 若未显式提供 success，则根据状态码推断
            if (!('success' in data)) {
              const pass = { success: this.statusCode >= 200 && this.statusCode < 400, ...data };
              return originalJson.call(this, pass);
            }
            return originalJson.call(this, data);
          }

            // 数组或原始类型，保持原样（兼容旧接口直接返回数组的用法）
            if (Array.isArray(data) || typeof data !== 'object' || data === null) {
              return originalJson.call(this, data);
            }

            // 默认标准化响应格式
          const response = {
            success: true,
            timestamp: new Date().toISOString(),
            data: data,
            ...(req.validationWarnings && req.validationWarnings.length > 0 && {
              warnings: req.validationWarnings
            })
          };

          return originalJson.call(this, response);
        } catch (e) {
          // 兜底：出现意外时不要阻断响应
          // 打印日志（忽略日志异常）
          console.error('responseFormatter包装失败:', e && (e.message || e));
          return originalJson.call(this, data);
        }
      };

      next();
    };
  }

  /**
   * 输入验证中间件工厂
   * 用法：app.post('/path', enhancedMiddleware.validateInput('pph_target'), handler)
   */
  validateInput(entityType) {
    return (req, res, next) => {
      if (!this.options.enableValidation) {
        return next();
      }

      try {
        const payload = req.body || {};
        const { isValid, errors, warnings, cleanedData } = this.validationService.validate(entityType, payload);

        // 将警告挂载到请求对象，便于 responseFormatter 输出
        req.validationWarnings = warnings || [];

        if (!isValid) {
          this.updateMetrics('validationError');
          return res.status(400).json({
            success: false,
            error: '数据验证失败',
            details: errors
          });
        }

        // 合并清洗后的安全数据（不破坏未在规则里的扩展字段）
        req.body = { ...payload, ...cleanedData };
        next();
      } catch (e) {
        console.error('验证服务执行异常:', e && (e.message || e));
        next(e);
      }
    };
  }

  /**
   * 健康检查端点
   */
  healthCheck(dbPool) {
    return async (req, res) => {
      try {
        const startTime = Date.now();
        
        // 测试数据库连接
        await dbPool.query('SELECT 1 as health_check');
        const dbResponseTime = Date.now() - startTime;
        
        // 获取系统状态
        const poolStatus = dbPool.getStatus();
        const poolMetrics = dbPool.getMetrics();
        
        const healthStatus = {
          status: 'healthy',
          timestamp: new Date().toISOString(),
          database: {
            connected: true,
            responseTime: dbResponseTime,
            poolStatus,
            metrics: poolMetrics
          },
          api: {
            metrics: this.getMetrics()
          },
          uptime: process.uptime()
        };

        // 检查是否有警告
        if (dbResponseTime > 1000) {
          healthStatus.warnings = ['数据库响应时间较慢'];
        }

        if (poolStatus.waitingQueue > 0) {
          healthStatus.warnings = healthStatus.warnings || [];
          healthStatus.warnings.push('数据库连接池有等待队列');
        }

        res.json(healthStatus);
      } catch (error) {
        res.status(503).json({
          status: 'unhealthy',
          timestamp: new Date().toISOString(),
          error: error.message,
          database: {
            connected: false
          }
        });
      }
    };
  }

  /**
   * 获取客户端ID
   */
  getClientId(req) {
    return req.ip || req.connection.remoteAddress || 'unknown';
  }

  /**
   * 清理过期的请求记录
   */
  cleanupExpiredRequests(windowStart) {
    for (const [clientId, requests] of this.requestCounts.entries()) {
      const validRequests = requests.filter(timestamp => timestamp > windowStart);
      if (validRequests.length === 0) {
        this.requestCounts.delete(clientId);
      } else {
        this.requestCounts.set(clientId, validRequests);
      }
    }
  }

  /**
   * 更新指标
   */
  updateMetrics(type) {
    if (!this.options.enableMetrics) return;

    switch (type) {
      case 'total':
        this.metrics.totalRequests++;
        break;
      case 'successful':
        this.metrics.successfulRequests++;
        break;
      case 'failed':
        this.metrics.failedRequests++;
        break;
      case 'validationError':
        this.metrics.validationErrors++;
        break;
      case 'rateLimitExceeded':
        this.metrics.rateLimitExceeded++;
        break;
    }
  }

  /**
   * 获取指标
   */
  getMetrics() {
    const successRate = this.metrics.totalRequests > 0 
      ? (this.metrics.successfulRequests / this.metrics.totalRequests) * 100 
      : 0;

    return {
      ...this.metrics,
      successRate: Math.round(successRate * 100) / 100
    };
  }

  /**
   * 重置指标
   */
  resetMetrics() {
    this.metrics = {
      totalRequests: 0,
      successfulRequests: 0,
      failedRequests: 0,
      validationErrors: 0,
      rateLimitExceeded: 0
    };
  }
}

module.exports = EnhancedMiddleware;
